<?xml version="1.0" encoding="UTF-8"?>
<!--
  Convert iTunes playlists to m3u
  -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1" xmlns:saxon="http://icl.com/saxon" xmlns="http://www.apple.com/DTDs/PropertyList-1.0.dtd">

  <xsl:output method="text"/>

  <!-- Create an index of the tracks: key is the track id, value is
  the track dictionary describing it. -->
  <xsl:key name="tracks" match="/plist/dict/dict/dict" use="preceding-sibling::key[1]/text()"/>

  <!-- Match only the playlists -->
  <xsl:template match="array[preceding-sibling::key/text() = 'Playlists']">
    <xsl:apply-templates mode="playlist"/>
  </xsl:template>

  <!-- Ignore all the playlists that are not visible and the "Master"
  playlist which is the whole library. -->
  <xsl:template match="key[text() = 'Name' and
  not(following-sibling::key[text() = 'Master' and following-sibling::true]) and
  not(following-sibling::key[text() = 'Visible' and following-sibling::false])]"
  	mode="playlist">
    <xsl:variable name="name" select="following-sibling::string[1]"/>
    <xsl:if test="not(following-sibling::key[text() = $name])">
      <xsl:text></xsl:text><xsl:value-of select="$name"/><xsl:text>
</xsl:text>
      <!-- Emit into a new .m3u file whose file name is that of the playlist -->
	  <xsl:document href="playlists/iTunes_{$name}.m3u" method="text" escape-uri-attributes="no">
        <!-- The .m3u heading required in each file -->
        <xsl:text>#CURTRACK 0
#EXTM3U
</xsl:text>
        <xsl:apply-templates select="following-sibling::array" mode="track"/>
      </xsl:document>
    </xsl:if>
  </xsl:template>

  <!-- On each track in the playlist we output #EXTINF followed by the
  name of the track, followed in the next line by the path to the
  actual file containing the song. -->
  <xsl:template match="dict" mode="track">
    <xsl:text>#EXTINF:-1,</xsl:text>
    <xsl:apply-templates select="key('tracks', integer)" mode="trackinfo"/>
    <xsl:text>
</xsl:text>
  </xsl:template>

  <!-- This extracts name and artist of the track and separates them by a dash -->
  <xsl:template match="key[text() = 'Name']" mode="trackinfo">
    <xsl:value-of select="concat(../key[text() = 'Artist']/following-sibling::string[1], ' - ',following-sibling::string[1])"/><xsl:text>
</xsl:text>
  </xsl:template>

  <!-- This extracts the file path from the track. It removes the
  file://localhost added by iTunes. -->
  <xsl:template match="key[text() = 'Location']" mode="trackinfo">
    <xsl:value-of select="following-sibling::string[1]"/>
  </xsl:template>

  <!-- Templates to recursively traverse the XML document. -->

  <xsl:template match="*|@*|text()">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="*|@*|text()" mode="playlist">
    <xsl:apply-templates mode="playlist"/>
  </xsl:template>

  <xsl:template match="*|@*|text()" mode="track">
    <xsl:apply-templates mode="track"/>
  </xsl:template>

  <xsl:template match="*|@*|text()" mode="trackinfo">
    <xsl:apply-templates mode="trackinfo"/>
  </xsl:template>

</xsl:stylesheet>
